package pm.oo.util;

import com.sun.star.awt.XSystemChildFactory;
import com.sun.star.awt.XToolkit;
import com.sun.star.awt.XWindow;
import com.sun.star.awt.XWindowPeer;
import com.sun.star.frame.XFrame;
import com.sun.star.frame.XFrames;
import com.sun.star.frame.XFramesSupplier;
import com.sun.star.uno.*;
import com.sun.star.lang.SystemDependent;
import pm.oo.OOException;

public class FramesUtil {
	private static final String FRAME_NAME = "PM_FRAME";

	public static XFrame createViewFrame(final Long hwnd) throws OOException {
		final XComponentContext xCtx = OfficeConnection.getOfficeContext();
		final Object frameObj;
		try {
			frameObj = xCtx.getServiceManager().createInstanceWithContext("com.sun.star.frame.Frame", xCtx);
		} catch (com.sun.star.uno.Exception e) {
			throw new OOException(e);
		}
		final XFrame xFrame = (XFrame) UnoRuntime.queryInterface(XFrame.class, frameObj);
		// get access to toolkit of remote office to create the container window of
		// new target frame
		final Object toolkitObj;
		try {
			toolkitObj = xCtx.getServiceManager().createInstanceWithContext("com.sun.star.awt.Toolkit", xCtx);
		} catch (com.sun.star.uno.Exception e) {
			throw new OOException(e);
		}
		final XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface(XToolkit.class, toolkitObj);
		final XSystemChildFactory xChildFactory = (XSystemChildFactory) UnoRuntime.queryInterface(XSystemChildFactory.class, xToolkit);
		/*
			Create an internal office window as child of our given java
			parent window.
			Try new version of creation: directly using of the window
			handle. The old implementation of the corresponding toolkit method
			requires a process ID. If this id isn't the right one a null object
			is returned. But normaly nobody outside the office knows this id.
			New version of this method ignore the id parameter and creation will
			work.
			Note: You must be shure if your window handle can be realy used by
			the remote office. Means if this java client and the remote office
			use the same display!
		*/
		final XWindowPeer xPeer = xChildFactory.createSystemChild(hwnd, null, SystemDependent.SYSTEM_WIN32); //todo
		// Cast it to the right return interface and return it.
		final XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, xPeer);
		xFrame.initialize(xWindow);
		// Insert the new frame in desktop hierarchy.
		// Use XFrames interface to do so. It provides access to the child frame container of that instance.
		final Object desktopObj;
		try {
			desktopObj = xCtx.getServiceManager().createInstanceWithContext("com.sun.star.frame.Desktop", xCtx);
		} catch (com.sun.star.uno.Exception e) {
			throw new OOException(e);
		}
		final XFramesSupplier xTreeRoot = (XFramesSupplier) UnoRuntime.queryInterface(XFramesSupplier.class, desktopObj);
		final XFrames xChildContainer = xTreeRoot.getFrames();
		xChildContainer.append(xFrame);
		// Make some further initializations on frame and window.
		xWindow.setVisible(true);
		xFrame.setName(FRAME_NAME);
		return xFrame;
	}

}
